home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Magazine / Online / OpenURL / Developer / Source / SmartReadArgs.c < prev    next >
C/C++ Source or Header  |  1999-09-26  |  24KB  |  738 lines

  1. /*
  2.  * SmartReadArgs.c -- CLI/Workbench transparent ReadArgs()
  3.  *
  4.  * $VER: SmartReadArgs.c 1.7 (7.9.98)
  5.  *
  6.  * Copyright 1998 by Thomas Aglassinger <agi@sbox.tu-graz.ac.at>
  7.  *
  8.  * Based on ExtReadArgs Copyright 1994,1995 by Stefan Ruppert
  9.  */
  10.  
  11. /****** SmartReadArgs/--history-- *******************************************
  12.  * HISTORY
  13.  *   Version 1.7
  14.  *   - TODO: use dos/FindArg() instead of is_in_template()
  15.  *   - Fixed two minor "size_t vs. LONG" warnings in
  16.  *
  17.  *   Version 1.6, 7-Sep-1998
  18.  *
  19.  *   - Changed name to SmartReadArgs to avoid confusion with other work based
  20.  *     on the same material
  21.  *   - Changed function parameters for SmartReadArgs() so that no more SAS/c
  22.  *     specific values of argc/argv are required (Of course it still works
  23.  *     with SAS/c, but you have to provide the WBStartup from "outside").
  24.  *   - Changed all #include <clib/...> to #include <proto/..>, except for
  25.  *     <clib/alib_stdio_protos.h> in "test.c". Where the hell is this one?
  26.  *   - Added feature to ignore tooltypes that are not in the template
  27.  *   - Added some missing includes in SmartReadArgs.c so the source codes
  28.  *     compile without warnings
  29.  *   - Changed #include <debug.h> to #include "debug.h" and provided a proper
  30.  *     debug.h
  31.  *   - The WINDOW tooltype is handled properly even if it is not entirely
  32.  *     written in upper case.
  33.  *   - Requires "utility.library" to be open as Stricmp() is used several
  34.  *     times
  35.  *   - Changed from Printf() to printf() using stdio of amiga.lib to make the
  36.  *     code compile easier on non-SAS environments
  37.  *   - Changed autodoc tool to Robodoc
  38.  *   - Fixed enforcer hit if no tooltypes were provided at all
  39.  *   - Remove some "char filename[34]" stuff and replaced the array dimension
  40.  *     by MAXIMUM_FILENAME_LENGTH for future compatibility
  41.  *   - Cleaned-up autodocs
  42.  * ANCIENT HISTORY
  43.  *   ExtReadArgs() by Stefan Ruppert
  44.  *
  45.  *   See aminet:dev/misc/extrdargs_v1.5.lha for the original version.
  46.  *
  47.  *   $HISTORY
  48.  *   08.01.95 : 001.005 :  changed to ExtReadArgs()
  49.  *   24.09.94 : 001.004 :  now checks after ReadArgs the SIGBREAKF_CTRL_C
  50.  *                         flag, thus if anyone canceled during ReadArgs()
  51.  *                         help ExtReadArgs() fails
  52.  *   08.09.94 : 001.003 :  between two switches (no equal sign) there was
  53.  *                         no space, this is fixed
  54.  *   08.09.94 : 001.002 :  wb files now enclosed in quotes
  55.  *   04.09.94 : 001.001 :  bumped to version 1
  56.  *   19.05.94 : 000.001 :  initial
  57.  ***************************************************************************/
  58.  
  59. /* ------------------------------ include's ------------------------------- */
  60.  
  61. #include "debug.h"
  62. #include "SmartReadArgs.h"
  63.  
  64. #include <exec/memory.h>
  65. #include <workbench/startup.h>
  66. #include <workbench/workbench.h>
  67. #include <dos/exall.h>
  68. #include <utility/tagitem.h>
  69.  
  70. #include <string.h>
  71.  
  72. #include <proto/dos.h>
  73. #include <proto/icon.h>
  74. #include <proto/exec.h>
  75. #include <proto/utility.h>
  76.  
  77. /* ---------------------------- local defines ----------------------------- */
  78.  
  79. #define TEMPSIZE                     512
  80. #ifndef MAX
  81. #define MAX(a,b)  (((a) > (b)) ? (a) : (b))
  82. #endif
  83.  
  84. #ifndef EOS
  85. #define EOS    '\0'
  86. #endif
  87.  
  88. #define MODE_MULTI      1
  89.  
  90. #define MAXIMUM_FILENAME_LENGTH 108
  91.  
  92. /* --------------------------- library bases ------------------------------ */
  93. extern struct Library *IconBase;
  94. extern struct Library *UtilityBase;
  95.  
  96. #ifdef __GNUC__
  97. extern struct WBStartup *_WBenchMsg;
  98. #endif
  99.  
  100. /* -------------------------- static prototypes --------------------------- */
  101.  
  102. static struct DiskObject *smart_get_icon(struct SmartArgs *args, struct WBStartup *wbarg);
  103. static void fstrcpy(struct SmartArgs *args, STRPTR string);
  104. static void get_arg_name(struct SmartArgs *args, STRPTR buffer, ULONG size, ULONG * modes);
  105. static void get_wbarg_name(struct WBArg *wbarg, STRPTR buffer, ULONG size);
  106. static BOOL is_in_template(STRPTR name, STRPTR template);
  107.  
  108. /****** SmartReadArgs/--background-- ****************************************
  109.  * COPYRIGHT
  110.  *   SmartReadArgs is Copyright 1998 Thomas Aglassinger
  111.  *
  112.  *   ExtReadArgs, its prequel, is Copyright 1994,1995 Stefan Ruppert
  113.  *
  114.  *   Permission is granted to freely distribute the material (also only
  115.  *   parts of it) as long this ReadMe is included and all the copyright
  116.  *   notes are left unaltered except for a description of your changes.
  117.  * MOTIVATION
  118.  *   The way of parsing ToolTypes provided by "icon.library" is rather
  119.  *   clumsy. This is particular annoying as many programmers and users got
  120.  *   used to ReadArgs(), which does the argument handling for many CLI
  121.  *   commands and ARexx ports.
  122.  *
  123.  *   Unfortunately, ReadArgs lacks a interface to Workbench tooltypes, thus
  124.  *   its usage preventes your programs from being started from Workbench.
  125.  *
  126.  *   SmartReadArgs() copies all Workbench arguments in a single string and
  127.  *   passes this string to the ReadArgs() function. If started from CLI, it
  128.  *   calls ReadArgs() without this step.
  129.  * AUTHOR
  130.  *   Stefan Ruppert wrote most parts of the source code, designed the general
  131.  *   interface and implemented loads of nice features. Basically he did the
  132.  *   "hard work".
  133.  *
  134.  *   He got the main idea for the implementation from Stefan Winterstein,
  135.  *   the author of ARoach.
  136.  *
  137.  *   Thomas Aglassinger <agi@sbox.tu-graz.ac.at> did some minor changes,
  138.  *   established a more consistent naming schema, reworked the documentation
  139.  *   and also added support for gcc/libnix.
  140.  *
  141.  *   Contact him in case of problems or if you made some enhancements.
  142.  *
  143.  *   Updates are available from aminet:dev/misc/SmartReadArgs.lha.
  144.  * DISCLAIMER
  145.  *   There is no warranty for this software package. Although the author
  146.  *   has tried to prevent errors, he can't guarantee that the software
  147.  *   package described in this document is 100% reliable. You are
  148.  *   therefore using this material at your own risk. The author cannot be
  149.  *   made responsible for any damage which is caused by using this
  150.  *   software package.
  151.  ****************************************************************************/
  152.  
  153. /* The define below is used to rename the example main() used in the autodoc
  154.  * to dummy_main(). Using two main()s would cause problems for the linker. */
  155. #define main dummy_main
  156.  
  157. /****** SmartReadArgs/SmartReadArgs ******************************************
  158.  * NAME
  159.  *   SmartReadArgs -- Workbench/CLI transparent ReadArgs().
  160.  * SYNOPSIS
  161.  *   error = SmartReadArgs(wb_startup, smart_args);
  162.  * 
  163.  *   LONG SmartReadArgs(struct WBStartup *, struct SmartArgs *);
  164.  * FUNCTION
  165.  *   This function is a CLI/Workbench transparent interface to ReadArgs().
  166.  *
  167.  *   In case of a Workbench start, it analyzes the WBStartup message and
  168.  *   possible tooltypes. These are converted to a text string that can be
  169.  *   passed to ReadArgs() like before.
  170.  *
  171.  *   Tooltypes that are not part of the template are ignored. This includes
  172.  *   tooltypes being disabled with "(...)", NewIcons image data on systems
  173.  *   without NewIcons installed and all this «« Icon by some idiot »» crap.
  174.  * 
  175.  *   If the application was stared from CLI, it simply calls ReadArgs()
  176.  *   without the conversion step.
  177.  *
  178.  *   If all went well you get a return value of zero. This means the passed
  179.  *   arguments fit the template and are ready to use. Otherwise you get a
  180.  *   IoErr()-like return code.
  181.  * INPUTS
  182.  *    wb_startup - Workbench startup message. Refer to your compiler manual
  183.  *        to learn how to obtain it. If this is NULL, the program was
  184.  *        started from CLI.
  185.  *    smart_args - structure which holds all information used by
  186.  *        SmartReadArgs(). You have to setup the following fields before the
  187.  *        call:
  188.  *
  189.  *        sa_Template - The template passed to ReadArgs()
  190.  *        sa_Parameter - ReadArgs() LONG WORD array to hold the arguments
  191.  *        sa_FileParameter - number of Argument in the template to use
  192.  *            for the files passed via WBStartup->sm_ArgList or -1, that
  193.  *            means you don't want any files
  194.  *        sa_Window - Window description string to open when the program
  195.  *            is started from the workbench. NULL means no window. If the
  196.  *            icon has a WINDOW tooltype, this value is ignored.
  197.  *        sa_RDArgs - RDArgs structure to use for ReadArgs() call. This
  198.  *            can be used to provide extended help.
  199.  *        sa_Buffer - Pointer to a buffer to use for the Workbench startup
  200.  *            or NULL, that means SmartReadArgs() allocates a buffer for you
  201.  *        sa_BufferSize - Size of the optional buffer. If it is smaller than
  202.  *            SA_MINIMUM_BUFFER_SIZE it will be adjusted.
  203.  *
  204.  *        All other fields should be set to NULL.
  205.  * RESULTS
  206.  *   Zero for success. You can check the sa_Flags field for the
  207.  *   SAF_WORKBENCH flag to learn how the program was started.
  208.  *
  209.  *   Otherwise an IoErr()-like error code is returned. This can be passed
  210.  *   directly to PrintFault() or similar.
  211.  * NOTES
  212.  *   Always call SmartFreeArgs(), even if SmartReadArgs() failed! See example
  213.  *   below.
  214.  *
  215.  *   This function requires "dos.library", "icon.library" and
  216.  *   "utility.library" to be opened by the application. Normally this
  217.  *   already has been done by the compiler startup code.
  218.  *
  219.  *   There is a not widely known feature of ReadArgs(): with templates like
  220.  *   "FROM/M/A,TO/A", you can select the files from workbench performing the
  221.  *   following steps:
  222.  *
  223.  *   - Select the program
  224.  *   - Select the FROM files
  225.  *   - Select and double click the TO file
  226.  *
  227.  *   This is available because ReadArgs() grabs the last string from a
  228.  *   multi-argument FROM and uses it as the TO parameter, if none is passed
  229.  *   explicitely.
  230.  * BUGS
  231.  *   There are some known problems when used with GCC, mostly related to the
  232.  *   fact that I never bothered creating a useable developer environment
  233.  *   around it (and I'm not sure if this is even possible >:) ...):
  234.  *
  235.  *   - Debugging output shows up in the console instead of SER:. Does
  236.  *     debug.lib exist for gcc? (Wasn't there this strange hunk2gcc
  237.  *     converter?)
  238.  *   - "Read from 0" Enforcer hit in SmartReadArgs(). Couldn't figure out
  239.  *     the exact location yet because of the asynchronous debugging output
  240.  *     mentioned above.
  241.  *
  242.  *   For someone with a reasonable experience with GCC, it should be easy to
  243.  *   fix this.
  244.  *
  245.  *   The SAS/c implementation does not have these problems.
  246.  * SEE ALSO
  247.  *   SmartFreeArgs(), dos.library/ReadArgs(), icon.library/GetDiskObjectNew()
  248.  * EXAMPLE
  249.  *   The main archiev comes with a "test.c" and a couple of icons to start
  250.  *   the corresponding executable "test". Take a look at the source code and
  251.  *   play with it.
  252.  *
  253.  *   See below for a smaller code segment that expects the "dos.library",
  254.  *   "icon.library" and "utility.library" to be open already.
  255.  * SOURCE
  256.  */
  257. int main(int argc, STRPTR argv[])
  258. {
  259.    struct SmartArgs smart_args =
  260.    {NULL};
  261.    LONG argument[2];
  262.    LONG error;
  263.  
  264.    /* Obtain WBStartup; depends on your compiler environment */
  265.    struct WBStartup *wb_startup = NULL;
  266. #ifdef __GNUC__
  267.    wb_startup = _WBenchMsg;
  268. #else
  269.    if (argc == 0)
  270.    {
  271.       wb_startup = (struct WBStartup *) argv;
  272.    }
  273. #endif
  274.  
  275.    smart_args.sa_Template = "FILES/M/A,VERBOSE";
  276.    smart_args.sa_Parameter = argument;
  277.    smart_args.sa_FileParameter = 0;
  278.    smart_args.sa_Window = "CON:////My WB-Window/AUTO/CLOSE/WAIT";
  279.  
  280.    error = SmartReadArgs(wb_startup, &smart_args);
  281.    if (error == 0)
  282.    {
  283.       /* do something */
  284.    }
  285.    else
  286.    {
  287.       PrintFault(error, "MyProgram");
  288.    }
  289.  
  290.    SmartFreeArgs(&smart_args);
  291.  
  292.    return ((error == 0) ? RETURN_OK : RETURN_FAIL);
  293. }
  294. /****************************************************************************/
  295. LONG SmartReadArgs(struct WBStartup * wb_startup, struct SmartArgs * args)
  296. {
  297.    LONG error;
  298.  
  299.    args->sa_Flags = 0;
  300.  
  301.    D(bug("UtilityBase = 0x%lx\n", (ULONG) UtilityBase));
  302.    D(bug("IconBase    = 0x%lx\n", (ULONG) IconBase));
  303.    D(bug("WBStartup   = 0x%lx\n", (ULONG) wb_startup));
  304.  
  305.    if (wb_startup != NULL)
  306.    {
  307.       struct WBArg *wbarg = wb_startup->sm_ArgList;
  308.       LONG arg_counter = 0;
  309.  
  310.       D(bug("  numArgs   = %ld\n", wb_startup->sm_NumArgs));
  311.       while (arg_counter < wb_startup->sm_NumArgs)
  312.       {
  313.          D(bug("  name[%ld] = \"%s\"\n", arg_counter, wbarg->wa_Name));
  314.          wbarg += 1;
  315.          arg_counter += 1;
  316.       }               
  317.    }
  318.  
  319.    if (wb_startup != NULL)
  320.    {
  321.       if (!(args->sa_RDArgs = AllocDosObject(DOS_RDARGS, NULL)))
  322.       {
  323.          return (ERROR_NO_FREE_STORE);
  324.       }
  325.       else
  326.       {
  327.          args->sa_Flags |= SAF_ALLOCRDARGS;
  328.  
  329.          if (!args->sa_Buffer)
  330.          {
  331.             args->sa_BufferSize = MAX(SA_MINIMUM_BUFFER_SIZE, args->sa_BufferSize);
  332.             args->sa_Buffer = AllocMem(args->sa_BufferSize, MEMF_ANY);
  333.             args->sa_Flags |= SAF_ALLOCBUFFER;
  334.          }
  335.  
  336.          if (!args->sa_Buffer)
  337.             return (ERROR_NO_FREE_STORE);
  338.          else
  339.          {
  340.             struct DiskObject *dobj;
  341.  
  342.             args->sa_ActualPtr = args->sa_Buffer;
  343.             args->sa_EndPtr = args->sa_Buffer + args->sa_BufferSize - 1;
  344.  
  345.             if (!(dobj = smart_get_icon(args, wb_startup)))
  346.             {
  347.                return (ERROR_OBJECT_NOT_FOUND);
  348.             }
  349.             else
  350.             {
  351.                struct WBArg *wbarg = args->sa_WBArg;
  352.                ULONG num = args->sa_NumArgs;
  353.  
  354.                STRPTR *tooltypes = (STRPTR *) dobj->do_ToolTypes;
  355.                STRPTR name;
  356.                STRPTR temp;
  357.                STRPTR ptr;
  358.  
  359.                if (num > 1 && args->sa_FileParameter >= 0 && (temp = AllocMem(TEMPSIZE, MEMF_ANY)))
  360.                {
  361.                   ULONG modes = 0;
  362.  
  363.                   get_arg_name(args, temp, TEMPSIZE, &modes);
  364.                   fstrcpy(args, temp);
  365.                   fstrcpy(args, " ");
  366.  
  367.                   /* no "/M" specifier in the ReadArgs() template, thus use only the first file */
  368.                   if (modes != MODE_MULTI)
  369.                      num = 2;
  370.  
  371.                   while (num > 1)
  372.                   {
  373.                      get_wbarg_name(wbarg, temp, TEMPSIZE);
  374.                      fstrcpy(args, "\"");
  375.                      fstrcpy(args, temp);
  376.                      fstrcpy(args, "\" ");
  377.                      num--;
  378.                      wbarg++;
  379.                   }
  380.  
  381.                   FreeMem(temp, TEMPSIZE);
  382.                }
  383.  
  384.                D(bug("tooltypes=%lx\n", (ULONG) tooltypes));
  385.                if (tooltypes)
  386.                {
  387.                   while (*tooltypes)
  388.                   {
  389.                      ptr = *tooltypes;
  390.                      name = ptr;
  391.  
  392.                      /* check if this tooltype enabled and part of the
  393.                       * template */
  394.                      if ((*ptr != '(')
  395.                          && is_in_template(name, args->sa_Template))
  396.                      {
  397.                         while (*ptr != '=' && *ptr != EOS)
  398.                            ptr++;
  399.  
  400.                         if (*ptr == '=')
  401.                         {
  402.                            *ptr = EOS;
  403.  
  404.                            if (!Stricmp(name, "WINDOW"))
  405.                            {
  406.                               STRPTR win;
  407.                               if ((win = AllocVec((ULONG) strlen(ptr + 1) + 1, MEMF_ANY)))
  408.                               {
  409.                                  strcpy(win, ptr + 1);
  410.                                  args->sa_Window = win;
  411.                                  args->sa_Flags |= SAF_ALLOCWINDOW;
  412.                               }
  413.  
  414.                            }
  415.                            else
  416.                            {
  417.                               fstrcpy(args, name);
  418.  
  419.                               /* enclose the argument in "" */
  420.                               if (*(ptr + 1) == '"')
  421.                               {
  422.                                  fstrcpy(args, "=");
  423.                                  fstrcpy(args, ptr + 1);
  424.                               }
  425.                               else
  426.                               {
  427.                                  fstrcpy(args, "=\"");
  428.                                  fstrcpy(args, ptr + 1);
  429.                                  fstrcpy(args, "\"");
  430.                               }
  431.  
  432.                               *ptr = '=';
  433.                            }
  434.                         }
  435.                         else
  436.                            fstrcpy(args, name);
  437.  
  438.                         fstrcpy(args, " ");
  439.                      }
  440.                      tooltypes++;
  441.                   }             /* while (*tooltypes) */
  442.                }                /* if (tooltypes) */
  443.                fstrcpy(args, "\n");
  444.  
  445.                D(bug("final wb command line : \"%s\"\n", args->sa_Buffer));
  446.             }
  447.          }
  448.       }
  449.  
  450.       args->sa_RDArgs->RDA_Source.CS_Buffer = args->sa_Buffer;
  451.       args->sa_RDArgs->RDA_Source.CS_Length = strlen(args->sa_Buffer);
  452.  
  453.       args->sa_Flags |= SAF_WORKBENCH;
  454.    }
  455.  
  456.    args->sa_FreeArgs = ReadArgs(args->sa_Template, args->sa_Parameter, args->sa_RDArgs);
  457.  
  458.    if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  459.    {
  460.       SetIoErr(ERROR_BREAK);
  461.    }
  462.  
  463.    if ((error = IoErr()) == 0 && (wb_startup != NULL))
  464.    {
  465.       if (args->sa_Window)
  466.       {
  467.          args->sa_WindowFH = Open(args->sa_Window, MODE_NEWFILE);
  468.          if (args->sa_WindowFH)
  469.          {
  470.             args->sa_OldOutput = SelectOutput(args->sa_WindowFH);
  471.             args->sa_OldInput = SelectInput(args->sa_WindowFH);
  472.          }
  473.       }
  474.    }
  475.  
  476.    return (error);
  477. }
  478.  
  479. /****** SmartReadArgs/SmartFreeArgs ******************************************
  480.  * NAME
  481.  *   SmartFreeArgs -- Free all resources allocated by SmartReadArgs().
  482.  * SYNOPSIS
  483.  *   SmartFreeArgs(smart_args);
  484.  *
  485.  *   void SmartFreeArgs(struct SmartArgs *);
  486.  * FUNCTION
  487.  *   Free all resources allocated by a previous call to SmartReadArgs().
  488.  * INPUTS
  489.  *   smart_args - Same pointer as passed to SmartReadArgs() before
  490.  * NOTES
  491.  *   Always call SmartFreeArgs(), even if SmartReadArgs() failed! Take a look
  492.  *   at the example for SmartReadArgs().
  493.  * SEE ALSO
  494.  *   SmartReadArgs()
  495.  ****************************************************************************/
  496. void SmartFreeArgs(struct SmartArgs *args)
  497. {
  498.    /* FreeArgs() can handle a NULL pointer */
  499.    FreeArgs(args->sa_FreeArgs);
  500.  
  501.    if (args->sa_Flags & SAF_ALLOCRDARGS)
  502.       if (args->sa_RDArgs)
  503.          FreeDosObject(DOS_RDARGS, args->sa_RDArgs);
  504.  
  505.    if (args->sa_Flags & SAF_ALLOCBUFFER)
  506.       FreeMem(args->sa_Buffer, args->sa_BufferSize);
  507.  
  508.    if (args->sa_WindowFH)
  509.    {
  510.       SelectOutput(args->sa_OldOutput);
  511.       SelectInput(args->sa_OldInput);
  512.       Close(args->sa_WindowFH);
  513.    }
  514.  
  515.    if (args->sa_Flags & SAF_ALLOCWINDOW && args->sa_Window)
  516.       FreeVec(args->sa_Window);
  517.  
  518. }
  519.  
  520. /* This code was grapped from IconImage/wbarg.c/IconFromWBArg()
  521.  * Commodore-Amiga Example code
  522.  */
  523. static struct DiskObject *smart_get_icon(struct SmartArgs *args, struct WBStartup *wb_startup)
  524. {
  525.    struct DiskObject *dob = NULL;
  526.    struct WBArg *wbarg = wb_startup->sm_ArgList;
  527.    ULONG num = wb_startup->sm_NumArgs;
  528.  
  529.    UBYTE work_name[MAXIMUM_FILENAME_LENGTH];
  530.    BPTR old_lock, new_lock;
  531.  
  532.    /* Copy the WBArg contents */
  533.    strncpy(work_name, wbarg->wa_Name, MAXIMUM_FILENAME_LENGTH);
  534.  
  535.    new_lock = DupLock(wbarg->wa_Lock);
  536.    if (new_lock != NULL)
  537.    {
  538.       D(bug("work_name : \"%s\"\n", work_name));
  539.  
  540.       /* go to the directory where the icon resides */
  541.       old_lock = CurrentDir(new_lock);
  542.  
  543.       dob = GetDiskObjectNew(work_name);
  544.  
  545.       /* test, if the first icon is a project icon and if so, get its icon */
  546.       if (wb_startup->sm_NumArgs > 1)
  547.       {
  548.          BPTR new_lock2;
  549.  
  550.          if ((new_lock2 = DupLock(wbarg[1].wa_Lock)))
  551.          {
  552.             struct DiskObject *prj;
  553.  
  554.             CurrentDir(new_lock2);
  555.  
  556.             UnLock(new_lock);
  557.             new_lock = new_lock2;
  558.  
  559.             strncpy(work_name, wbarg[1].wa_Name, MAXIMUM_FILENAME_LENGTH);
  560.             D(bug("work_name2 : \"%s\"\n", work_name));
  561.  
  562.             if ((prj = GetDiskObjectNew(work_name)))
  563.             {
  564.                if (prj->do_Type == WBPROJECT)
  565.                {
  566.                   BPTR test;
  567.  
  568.                   /* if this is only an icon skip it */
  569.                   if (!(test = Lock(work_name, SHARED_LOCK)))
  570.                   {
  571.                      wbarg++;
  572.                      num--;
  573.                   }
  574.                   else
  575.                      UnLock(test);
  576.  
  577.                   if (dob)
  578.                      FreeDiskObject(dob);
  579.  
  580.                   dob = prj;
  581.                }
  582.             }
  583.          }
  584.       }
  585.  
  586.       if (dob)
  587.       {
  588.          D(bug("dobj window : %s\n", dob->do_ToolWindow));
  589.       }
  590.  
  591.       /* go back to where we used to be */
  592.       CurrentDir(old_lock);
  593.  
  594.       /* release the duplicated lock */
  595.       UnLock(new_lock);
  596.  
  597.       args->sa_WBArg = wbarg + 1;
  598.       args->sa_NumArgs = num;
  599.    }
  600.  
  601.    D(bug("return (dob)\n"));
  602.  
  603.    return (dob);
  604. }
  605.  
  606. static void fstrcpy(struct SmartArgs *args, STRPTR string)
  607. {
  608.    STRPTR ptr = args->sa_ActualPtr;
  609.    STRPTR end = args->sa_EndPtr;
  610.  
  611.    while (ptr < end && *string)
  612.       *ptr++ = *string++;
  613.  
  614.    *ptr = EOS;                  /* Mark end of string */
  615.  
  616.    args->sa_ActualPtr = ptr;
  617. }
  618.  
  619. static void get_arg_name(struct SmartArgs *args, STRPTR buffer, ULONG size, ULONG * modes)
  620. {
  621.    ULONG num = args->sa_FileParameter;
  622.    STRPTR ptr = args->sa_Template;
  623.  
  624.    *modes = 0;
  625.  
  626.    while (num > 0)
  627.    {
  628.       while (*ptr != ',' && *ptr != EOS)
  629.          ptr++;
  630.  
  631.       if (*ptr == ',')
  632.          ptr++;
  633.       num--;
  634.    }
  635.  
  636.    if (*ptr != EOS)
  637.    {
  638.       while (*ptr != ',' && *ptr != '/' && *ptr != EOS && size > 0)
  639.       {
  640.          *buffer++ = *ptr++;
  641.          size--;
  642.       }
  643.  
  644.       while (*ptr == '/')
  645.       {
  646.          ptr++;
  647.  
  648.          if (*ptr == 'M' || *ptr == 'm')
  649.             *modes = MODE_MULTI;
  650.  
  651.          ptr++;
  652.       }
  653.    }
  654.  
  655.    *buffer = EOS;
  656. }
  657.  
  658. static void get_wbarg_name(struct WBArg *wbarg, STRPTR buffer, ULONG size)
  659. {
  660.    BPTR new;
  661.  
  662.    if ((new = DupLock(wbarg->wa_Lock)))
  663.    {
  664.       if (!NameFromLock(new, buffer, size))
  665.          *buffer = EOS;
  666.       else if (!AddPart(buffer, wbarg->wa_Name, size))
  667.          *buffer = EOS;
  668.  
  669.       UnLock(new);
  670.    }
  671.    else
  672.       *buffer = EOS;
  673. }
  674.  
  675. /* Enable extended debugging for is_in_template() */
  676. #if 0
  677. #define D2(x) x
  678. #else
  679. #define D2(x) /* nufin */
  680. #endif
  681. static BOOL is_in_template(STRPTR name, STRPTR template)
  682. {
  683.    BOOL found = FALSE;
  684.    STRPTR current_word = template;
  685.    BOOL skip_switch = FALSE;
  686.    size_t name_length;
  687.  
  688.    /* Evaluate length of name part of whole tooltype */
  689.    name_length = 0;
  690.    while ((name[name_length] != EOS)
  691.           && (name[name_length] != '='))
  692.    {
  693.       name_length += 1;
  694.    }
  695.  
  696.    D(bug("find `%s' in template `%s'\n", name, template));
  697.    while ((current_word[0] != '\0') && (!found))
  698.    {
  699.       STRPTR next_word = strpbrk(current_word, "/=,");
  700.       size_t current_word_length;
  701.  
  702.       if (next_word == NULL)
  703.       {
  704.          next_word = current_word + strlen(current_word);
  705.       }
  706.       current_word_length = next_word - current_word;
  707.  
  708.       if (skip_switch)
  709.       {
  710.          D2(bug("  skip  (`%s', %lu)\n", current_word, current_word_length));
  711.          skip_switch = FALSE;
  712.       }
  713.       else
  714.       {
  715.          D2(bug("  check (`%s', %lu)\n", current_word, current_word_length));
  716.          if ((name_length == current_word_length)
  717.              && !Strnicmp(name, current_word, (LONG) name_length))
  718.          {
  719.             D(bug("  found!\n"));
  720.             found = TRUE;
  721.          }
  722.       }
  723.  
  724.       current_word = next_word;
  725.       if (current_word[0] != '\0')
  726.       {
  727.          if (current_word[0] == '/')
  728.          {
  729.             skip_switch = TRUE;
  730.          }
  731.          current_word += 1;
  732.       }
  733.    }
  734.  
  735.    return found;
  736. }
  737.  
  738.